/// An AXI4 interface.
interface AXI_BUS #(
  parameter int unsigned AXI_ADDR_WIDTH = 0,
  parameter int unsigned AXI_DATA_WIDTH = 0,
  parameter int unsigned AXI_ID_WIDTH   = 0,
  parameter int unsigned AXI_USER_WIDTH = 0
);

  localparam int unsigned AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8;

  typedef logic [AXI_ID_WIDTH-1:0]   id_t;
  typedef logic [AXI_ADDR_WIDTH-1:0] addr_t;
  typedef logic [AXI_DATA_WIDTH-1:0] data_t;
  typedef logic [AXI_STRB_WIDTH-1:0] strb_t;
  typedef logic [AXI_USER_WIDTH-1:0] user_t;

  typedef logic [1:0]  burst_t;
  typedef logic [1:0]   resp_t;
  typedef logic [3:0]  cache_t;
  typedef logic [2:0]   prot_t;
  typedef logic [3:0]    qos_t;
  typedef logic [3:0] region_t;
  typedef logic [7:0]    len_t;
  typedef logic [2:0]   size_t;

  id_t              awid;
  addr_t            awaddr;
  len_t             awlen;
  size_t            awsize;
  burst_t           awburst;
  logic             awlock;
  cache_t           awcache;
  prot_t            awprot;
  qos_t             awqos;
  region_t          awregion;
  user_t            awuser;
  logic             awvalid;
  logic             awready;

  data_t            wdata;
  strb_t            wstrb;
  logic             wlast;
  user_t            wuser;
  logic             wvalid;
  logic             wready;

  id_t              bid;
  resp_t            bresp;
  user_t            buser;
  logic             bvalid;
  logic             bready;

  id_t              arid;
  addr_t            araddr;
  len_t             arlen;
  size_t            arsize;
  burst_t           arburst;
  logic             arlock;
  cache_t           arcache;
  prot_t            arprot;
  qos_t             arqos;
  region_t          arregion;
  user_t            aruser;
  logic             arvalid;
  logic             arready;

  id_t              rid;
  data_t            rdata;
  resp_t            rresp;
  logic             rlast;
  user_t            ruser;
  logic             rvalid;
  logic             rready;

  modport Master (
      output awid, awaddr, awlen, awsize, awburst, awlock, awcache, awprot, awqos, awregion, awuser, awvalid, 
      input awready,
      output wdata, wstrb, wlast, wuser, wvalid,
      input wready,
      input bid, bresp, buser, bvalid,
      output bready,
      output arid, araddr, arlen, arsize, arburst, arlock, arcache, arprot, arqos, arregion, aruser, arvalid, 
      input arready,
      input rid, rdata, rresp, rlast, ruser, rvalid,
      output rready
    );

    modport Slave (
      input awid, awaddr, awlen, awsize, awburst, awlock, awcache, awprot, awqos, awregion, awuser, awvalid,
      output awready,
      input wdata, wstrb, wlast, wuser, wvalid,
      output wready,
      output bid, bresp, buser, bvalid,
      input bready,
      input arid, araddr, arlen, arsize, arburst, arlock, arcache, arprot, arqos, arregion, aruser, arvalid,
      output arready,
      output rid, rdata, rresp, rlast, ruser, rvalid, 
      input rready
    );
    
endinterface
